﻿using System.Dynamic;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using AutoTest.Common.Extension;
using AutoTest.Common.UtilsHelper;
using EasyTool;

namespace AutoTest.Common
{
    /// <summary>
    /// 全局的扩展方法，慎重添加
    /// </summary>
    public static class GlobalExtension
    {
        #region 检查对象
        /// <summary>
        /// 检查是否为空
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool IsNull(this object? obj) => obj == null;

        /// <summary>
        /// 检查是否为空，不为空范湖true
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool IsNotNull(this object obj) => !IsNull(obj);
        /// <summary>
        /// 检查是否为空，为空抛出异常
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="parameterName"></param>
        public static void CheckNull(this object obj, string parameterName = "")
        {
            if (obj == null) throw new ArgumentException(parameterName);
        }

        /// <summary>
        /// 检查继承关系
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool Is<T>(this object obj)
        {

            return obj is T || obj.Is(typeof(T));
        }

        /// <summary>
        /// 判断继承关系
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static bool Is(this object obj, Type type)
        {
            return type.IsInstanceOfType(obj) || type.IsAssignableFrom(obj.GetType());
        }

        /// <summary>
        /// 不是
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static bool IsNot(this object obj, Type type)
        {
            return !Is(obj, type);
        }

        /// <summary>
        /// 不是
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool IsNot<T>(this object obj)
        {
            return !Is<T>(obj);
        }

        #endregion

        #region 序列化
        /// <summary>
        /// 对象序列化Json
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string ToJson(this object obj,bool camelCase = false,bool ignoreNull = true)
        {
            string strJson = string.Empty;
            JsonSerializerOptions option = new();
            if (obj != null)
            {
                if (camelCase)
                {
                    option.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
                }

                if (ignoreNull)
                {
                    option.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
                }


                strJson = JsonSerializer.Serialize(obj, option);

            }
            return strJson;
        }
     

        /// <summary>
        /// 序列化成xml（不支持对象嵌套对象）
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="ignoreNullOrEmpty"></param>
        /// <returns></returns>
        public static string ToXml(this object obj,bool ignoreNullOrEmpty = false)
        {
            string strXml = string.Empty;
            if (obj != null)
            {
                strXml = XmlHelper.ToXml(obj, ignoreNullOrEmpty);
            }
            return strXml;
        }

        #endregion

        #region 转换
        /// <summary>
        /// 将对象转换需要的类型（会判断能否转）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static T CastTo<T>(this object obj)
        {
            T defaultValue = default!;

            if (obj.IsNotNull() && obj.Is<T>())
            {
                defaultValue = (T)obj;
            }
            return defaultValue;
        }

        /// <summary>
        /// 将对象转换需要的类型（不能转就会抛出异常）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static T CastNoSafe<T>(this object obj)
        {
            T defaultValue = default!;

            if (obj.IsNotNull())
            {
                defaultValue = (T)obj;
            }

            return defaultValue;
        }

        /// <summary>
        /// 根据字段名字进行Copy对象，浅拷贝
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static T Copy<T>(this object obj) where T : class,new()
        {
            return Copy<T>(obj,null!);
        }

        /// <summary>
        /// 拷贝
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source">取值对象</param>
        /// <param name="target">赋值对象</param>
        /// <returns></returns>
        public static T Copy<T>(this object source, T target) where T : class, new()
        {
            if (source == null) return target;
            Type type = typeof(T);
            PropertyInfo[] properties = type.GetProperties();
            if (target.IsNull()) target = Activator.CreateInstance<T>();
            if (properties != null && properties.Length > 0)
            {
                foreach (var property in properties)
                {
                    try
                    {
                        string propertyName = property.Name;
                        var sourceProperty = source.GetType().GetProperty(propertyName);
                        if (sourceProperty != null)
                        {
                            MethodInfo getmethod = sourceProperty.GetGetMethod(false)!;
                            MethodInfo setmethod = property.GetSetMethod(false)!;
                            if (getmethod != null && setmethod != null)
                            {
                                setmethod.Invoke(target, new object[] { getmethod.Invoke(source, null)! });
                            }
                        }
                    }
                    catch (Exception) { }
                }
            }
            return target;
        }

        public static T CopyFrom<T>(this T target,object source) where T : class,new()
        {
            if (source is null) return target;
            return source.Copy(target);
        }

        /// <summary>
        /// 对象的属性转成字典
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        public static Dictionary<string, object> ToDictionary(this object o, bool ignoreNull = true)
        {
            Dictionary<string, object> map = new();
            if (o == null) return map;

            Type t = o.GetType();

            PropertyInfo[] pi = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            if ((pi?.Length ?? 0) == 0) return new Dictionary<string, object>();

            foreach (PropertyInfo p in pi!)
            {
                MethodInfo mi = p.GetGetMethod()!;

                if (mi != null && mi.IsPublic)
                {
                    var v = mi.Invoke(o, null);
                    if (v == null && ignoreNull) continue;
                    else if (v == null)
                    {
                        map[p.Name] = v!;
                        continue;
                    }
                    if (p.PropertyType.IsValueType || p.PropertyType.FullName == typeof(string).FullName)
                    {
                        map.Add(p.Name, v);
                    }
                    else if (typeof(System.Collections.IEnumerable).IsAssignableFrom(p.PropertyType))
                    {
                        var array = new List<Dictionary<string, object>>();
                        var iv = (System.Collections.IEnumerable)v;
                        var enumartor = iv.GetEnumerator();
                        while (enumartor.MoveNext())
                        {
                            var item = enumartor.Current;
                            array.Add(item.ToDictionary());
                        }
                        map.Add(p.Name, array);
                    }
                    else
                    {
                        map.Add(p.Name, v.ToDictionary());
                    }

                }
            }

            return map;

        }

        #endregion

        /// <summary>
        /// 为属性赋值
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="model"></param>
        /// <param name="propertyName"></param>
        /// <param name="propertyValue"></param>
        /// <returns></returns>
        public static TModel? SetProperty<TModel, TProperty>(this TModel model, string propertyName, TProperty propertyValue)
        {
            PropertyInfo propertyInfo = typeof(TModel).GetProperty(propertyName)!;
            propertyInfo?.SetValue(model, propertyValue);
            return model;
        }

        /// <summary>
        /// 获得属性值
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        public static object? GetProperty(this object obj, string propertyName)
        {
            PropertyInfo propertyInfo = obj.GetType().GetProperty(propertyName)!;
            return propertyInfo?.GetValue(obj);
        }

        /// <summary>
        /// 获取动态对象的属性
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        public static  object GetValue(this ExpandoObject obj,string propertyName)
        {
            Dictionary<string, object> dict = obj.ToDictionary();
            return dict.GetDictValue(propertyName);
        }
    }
}